home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HyperLib 1997 Winter - Disc 1
/
HYPERLIB-1997-Winter-CD1.ISO.7z
/
HYPERLIB-1997-Winter-CD1.ISO
/
オンラインウェア
/
UTIL
/
Folder・Icon・Opener 1.0.1.sit
/
Folder•Icon•Opener 1.0.1
/
source code
/
sources
/
FIOpen.open.c
< prev
next >
Wrap
Text File
|
1996-05-05
|
11KB
|
365 lines
/*
*--------------------------------------------------------------
* FIOpen.open.c
*--------------------------------------------------------------
* Most of source codes in this file come from StandardGetFolder
* example written by Steve Falkenburg -- MacDTS, Apple Computer.
* However, the author fully rewrite the codes in order to avoid
* using global variables and make it PowerPC applicable.
*--------------------------------------------------------------
* Written by Fumio Rokkaku, 1995-1996
*--------------------------------------------------------------
*/
#pragma once
/* System Headers */
#include <Memory.h>
#include <Dialogs.h>
#include <Controls.h>
#include <Files.h>
#include <Folders.h>
#include <Finder.h>
#include <Aliases.h>
#include <Script.h>
#include <StandardFile.h>
/* Project Headers */
#include "FIOpen.h"
/* set __USE_DEBUGER to 1 when you use debugger on 68K Mac */
#define __USE_DEBUGER 0
#define __DEBUG_68K (__USE_DEBUGER && !__powerpc)
/*
*--------------------------------------------------------------
* constants
*--------------------------------------------------------------
*/
enum constGetFolderIDs {
kStdGetFolderID = 1000,
kStrFolderID = kStdGetFolderID
};
enum constGetFolderItems {
sfItemFolderButton = 10
};
enum constGetFolderStrs {
iSelectIdx = 1,
iDsktopIdx = 2,
iFolderIdx = 3
};
/*
*--------------------------------------------------------------
* type definition
*--------------------------------------------------------------
*/
typedef struct {
StandardFileReply *sfReply;
FSSpec prevSpec;
FSSpec deskSpec;
Str15 dskTop;
Str15 select;
unsigned char quoBgn;
unsigned char quoEnd;
} SFUserDataRec, *SFUserDataPtr;
/*
*--------------------------------------------------------------
* prototypes
*--------------------------------------------------------------
*/
/* file filter procedures */
pascal Boolean MyCustomFileFilter(CInfoPBPtr, void *);
pascal short MyCustomSFHook(short, DialogRef, void *);
/* static functions only used in this source */
static void SetUpMyHookData(SFUserDataPtr);
static OSErr MakeCanonFSSpec(FSSpecPtr);
static OSErr GetDesktopFolderSpec(const short, FSSpecPtr);
static void SetSelectButtonName(DialogRef, StringPtr, SFUserDataPtr);
static void DimTheButton(DialogRef, Boolean);
static Boolean EqualFSSpec(const FSSpecPtr, const FSSpecPtr);
/*
*--------------------------------------------------------------
* StandardGetFolder
*--------------------------------------------------------------
* it provides "Select file and folder" dialog
* note that this can be used only on System7 or greater
*--------------------------------------------------------------
*/
void CustomGetFolderOnly(StandardFileReply *theReply)
{
Point openPt;
SFTypeList aList;
FileFilterYDUPP MyFileFilterUPP = nil;
DlgHookYDUPP MyDialogHookUPP = nil;
SFUserDataRec sfUserData;
/* initialize the reply flag */
theReply->sfGood = false;
/* initialize dailog location with ridiculous values */
openPt.v = openPt.h = -1;
/* initialize user data */
sfUserData.sfReply = theReply;
sfUserData.prevSpec.vRefNum = -9999; /* init to ridiculous value */
/* load constant strings */
GetIndString(sfUserData.select, kStrFolderID, iSelectIdx);
GetIndString(sfUserData.dskTop, kStrFolderID, iDsktopIdx);
/* set quotation mark characters */
if (FontScript() != smRoman) {
sfUserData.quoBgn = '"';
sfUserData.quoEnd = '"';
} else {
sfUserData.quoBgn = 'メ';
sfUserData.quoEnd = 'モ';
}
/* install hook and file filter UPPs */
MyFileFilterUPP = NewFileFilterYDProc(MyCustomFileFilter);
MyDialogHookUPP = NewDlgHookYDProc(MyCustomSFHook);
/* if the UPPs are valid, then... */
if ((MyFileFilterUPP != nil) && (MyDialogHookUPP != nil)) {
/* open get folder dialog */
CustomGetFile(MyFileFilterUPP, -1, aList, theReply, kStdGetFolderID,
openPt, MyDialogHookUPP, nil, nil, nil, &sfUserData);
/* clean up the UPPs */
DisposeRoutineDescriptor(MyFileFilterUPP);
DisposeRoutineDescriptor(MyDialogHookUPP);
}
}
/*
*--------------------------------------------------------------
* MyCustomFileFilter
*--------------------------------------------------------------
* this filter passes only visible folders
*--------------------------------------------------------------
*/
pascal Boolean MyCustomFileFilter(CInfoPBPtr thePB, void *userData)
{
#pragma unused(userData)
unsigned short fileFlags = thePB->hFileInfo.ioFlFndrInfo.fdFlags;
char fileAttrb = thePB->hFileInfo.ioFlAttrib;
return (
((fileAttrb & ioDirMask) == 0)
|| ((fileFlags & kIsInvisible) != 0)
);
}
/*
*--------------------------------------------------------------
* MyCustomSFHook
*--------------------------------------------------------------
* this dialog hook checks the contents of the additional edit
* fields when the user selects a file. The focus of the dialog
* is changed if one of the fields is out of range.
*--------------------------------------------------------------
*/
pascal short MyCustomSFHook(short theItem, DialogRef theDialog, void *userData)
{
#if __DEBUG_68K
/* this is not needed at runtime but just for debugging on 68K Mac */
long oldA5 = SetA5(SetCurrentA5());
#endif
SFUserDataPtr sfUserData;
StandardFileReply *sfUserRepl;
FSSpecPtr sfReplSpec, sfPrevSpec;
if (GetWRefCon(GetDialogWindow(theDialog)) != sfMainDialogRefCon) {
return (theItem);
}
/* copy SFUserData structure's pointers and contents */
sfUserData = (SFUserDataPtr)userData;
sfUserRepl = sfUserData->sfReply;
sfPrevSpec = &sfUserData->prevSpec;
sfReplSpec = &sfUserRepl->sfFile;
/* check dialog button operations */
switch (theItem) {
case sfHookFirstCall:
/* ====
This is a sample to locate a default folder when the dialog is firstly openeFIOpen...
This sample opens the system folder at always the dialog is opneFIOpen.
You can give a folder you want to specify in the sfUserRepl->sfIsFolder before
calling StandardGetFolder.
==== */
/* ====
if (FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
&sfReplSpec->vRefNum, &sfReplSpec->parID) == noErr) {
theItem = sfHookChangeSelection;
}
==== */
break;
case sfItemVolumeUser:
/* if volume is changed, */
sfReplSpec->name[0] = 0;
sfReplSpec->parID = fsRtDirID;
sfUserRepl->sfIsFolder = false;
sfUserRepl->sfIsVolume = false;
sfUserRepl->sfFlags = 0;
theItem = sfHookChangeSelection;
break;
case sfItemFolderButton:
/* when the folder select button is pressed, make it to be selected */
theItem = sfItemOpenButton;
break;
case sfHookNullEvent:
/* check currently selected file or folder item */
if (EqualFSSpec(sfReplSpec, sfPrevSpec) == false) {
FSSpec currSpec;
currSpec = *sfReplSpec;
MakeCanonFSSpec(&currSpec);
/* get a desktop folder of the newly selected volume */
if (currSpec.vRefNum != sfPrevSpec->vRefNum) {
GetDesktopFolderSpec(currSpec.vRefNum, &sfUserData->deskSpec);
}
/* if the current folder is the desktop, dim the select button */
DimTheButton(theDialog, EqualFSSpec(&sfUserData->deskSpec, &currSpec));
/* show the currently selected file or folder in the button */
SetSelectButtonName(theDialog, currSpec.name, sfUserData);
*sfPrevSpec = *sfReplSpec;
}
break;
case sfHookLastCall:
/* if none is selected, return the parent folder */
if (Length(sfReplSpec->name) == 0) {
MakeCanonFSSpec(sfReplSpec);
}
break;
}
#if __DEBUG_68K
(void)SetA5(oldA5);
#endif
return (theItem);
}
/*
*--------------------------------------------------------------
* MakeCanonFSSpec
*--------------------------------------------------------------
* when the given FSSpec name is empty,
* make its parent directory spec
*--------------------------------------------------------------
*/
static OSErr MakeCanonFSSpec(FSSpecPtr theSpec)
{
OSErr result = noErr;
if (Length(theSpec->name) == 0) {
result = FSMakeFSSpec(theSpec->vRefNum, theSpec->parID, nil, theSpec);
}
return (result);
}
/*
*--------------------------------------------------------------
* GetDesktopFolderSpec
*--------------------------------------------------------------
* get an FSSpec that indicates the volume's desktop
*--------------------------------------------------------------
*/
static OSErr GetDesktopFolderSpec(
const short theVRefNum,
FSSpecPtr theFolderSpec)
{
OSErr result;
theFolderSpec->name[0] = 0;
result = FindFolder(theVRefNum, kDesktopFolderType, kDontCreateFolder,
&theFolderSpec->vRefNum, &theFolderSpec->parID);
if (result == noErr) {
result = MakeCanonFSSpec(theFolderSpec);
}
return (result);
}
/*
*--------------------------------------------------------------
* SetSelectButtonName
*--------------------------------------------------------------
* set name of the folder/file select button
*--------------------------------------------------------------
*/
static void SetSelectButtonName(
DialogRef theDialog,
StringPtr selectedName,
SFUserDataPtr showStrs)
{
Handle folderBttn;
Str255 bttnTitle;
Str63 tempSelectName;
Rect iRect;
short iType;
/* get folder select button */
GetDialogItem(theDialog, sfItemFolderButton, &iType, &folderBttn, &iRect);
{ /* truncate file or folder name if it is wider than the button */
short bttnWidth =
(iRect.right - iRect.left) - 4
- StringWidth(showStrs->select)
- (CharWidth(showStrs->quoBgn) * 2);
PStrCpy(selectedName, tempSelectName);
TruncString(bttnWidth, tempSelectName, smTruncMiddle);
}
/* make a new button title */
PStrCpy(showStrs->select, bttnTitle); /* "Select " */
CatChar(showStrs->quoBgn, bttnTitle); /* "メ" or """ */
PStrCat(tempSelectName, bttnTitle); /* "(file or folder name)" */
CatChar(showStrs->quoEnd, bttnTitle); /* "モ" or """ */
/* set new button title */
SetControlTitle((ControlRef)folderBttn, bttnTitle);
}
/*
*--------------------------------------------------------------
* DimTheButton
*--------------------------------------------------------------
* deactivate/activate the "folder select" button
*--------------------------------------------------------------
*/
static void DimTheButton(DialogRef theDialog, Boolean makeItDim)
{
Handle aButton; Rect aRect; short aType;
GetDialogItem(theDialog, sfItemFolderButton, &aType, &aButton, &aRect);
HiliteControl((ControlRef)aButton, (makeItDim) ? kControlInactivePart : kControlNoPart);
}
/*
*--------------------------------------------------------------
* EqualFSSpec
*--------------------------------------------------------------
* compare two FSSpec contents, turn true if they are the same
*--------------------------------------------------------------
*/
static Boolean EqualFSSpec(const FSSpecPtr specA, const FSSpecPtr specB)
{
return (
specA->vRefNum == specB->vRefNum
&& specA->parID == specB->parID
&& EqualString(specA->name, specB->name, false, true)
);
}